home *** CD-ROM | disk | FTP | other *** search
Wrap
/* ========================================================================== File: DiamondDef.c Function: Defines the Diamond Window. History: 7/4/90 & 8/26/90 - 12/1/90 & 2/15/91 - 4/22/91 : Marz. ============================================================================= */ #include "DiamondDef.h" #include <SetUpA4.h> #define wJUST_DRAGGED 50 #define wNEW_TITLE 51 #define DRAW_WINDOW_FRAME 0 #define ZOOM_MASK 8 #define NO_GROW_MASK 4 #define SCREEN_MARGIN 3 #define FRAME_WIDTH 25 #define SHADOW 3 #define LEFT_SIDE TRUE #define FULL_RESERVE 51 #define TOP_RESERVE 30 #define BOTTOM_RESERVE 13 #define FIRST_CHAR 1 static Pattern white = {0}, black = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF}, gray = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55}; DataRecord dataRecord; DataRecordHdl dataRecordHdl; /* =========================================================================== */ void CalcRgns(WindowPeek theWindow) { /* Calculates the structure, content, and title regions of diamond windows when they are created or after they have been dragged or resized. */ GrafPtr savedPort; Rect theRect, strucRect, polyRect; short halfPort, halfStruc, xOffset, yOffset; theRect = theWindow->port.portRect; /* The contentRgn extends beyond the portRect. This means origin is automatically offset so that it begins just outside the scroll bar area, regardless of whether or not the window actually has a grow region. */ halfPort = halfStruc = (theRect.right - theRect.left) >> 1; halfStruc += 26; /* This routine needs the portRect in Global coordinates for drawing in the WMgr port. By switching the current port to the window's port and pretending a rectangle is two points this can be achieved. */ GetPort(&savedPort); SetPort(theWindow); LocalToGlobal(&topLeft(theRect)); LocalToGlobal(&botRight(theRect)); SetPort(savedPort); if (EqualRect(&theRect, &dataRecord.stdRect)) { /* window was resized by being zoomed, don't change dataRecord.myRect, it holds the previous size of the portRect for use with inZoomIn. */ strucRect = theRect; dataRecord.zoomedOut = TRUE; } else { /* window has been resized w/o being zoomed, save the new window size for later inZoom-ing. */ dataRecord.myRect = strucRect = theRect; dataRecord.zoomedOut = FALSE; } /* Get the strucRect. dataRecord.midX and dataRecord.midY are the Global coordinates of the middle of the window. */ InsetRect(&strucRect, -26, -26); dataRecord.midX = (strucRect.left + strucRect.right) >> 1; dataRecord.midY = (strucRect.top + strucRect.bottom) >> 1; /* Get the strucRgn */ OpenRgn(); MoveTo(strucRect.left, dataRecord.midY); Line(halfStruc, -halfStruc); Line(2, 0); Line(halfStruc, halfStruc); Line(0, 1); Line(-halfStruc, halfStruc); Line(-2, 0); Line(-halfStruc, -halfStruc); Line(0, -1); CloseRgn(theWindow->strucRgn); /* Define the titleRgn. There are a couple of notes of interest here. 1) ErasePoly() actually calls NewRgn() and makes a region out of the polygon in order to know what to erase. 2) I only used titlePoly to erase the title area anyway so why not just make it a region and save time? */ OpenRgn(); MoveTo(theRect.left - 26, dataRecord.midY); Line(26, 0); Line(halfPort, halfPort); Line(halfPort, -halfPort); Line(26, 0); Line(-halfStruc, halfStruc); Line(-halfStruc, -halfStruc); CloseRgn(dataRecord.titleRgn); /* Define the content region. */ halfStruc --; OpenRgn(); MoveTo(dataRecord.midX, theRect.top - 25); Line(halfStruc, halfStruc); Line(-25, 0); Line(-halfPort, halfPort); Line(-halfPort, -halfPort); Line(-25, 0); Line(halfStruc, -halfStruc); CloseRgn(theWindow->contRgn); /* The following lines offset various window parts to the updated locations. The window parts are only updated if they are present. */ if (theWindow->goAwayFlag) { HLock(dataRecord.goAwayPoly); polyRect = (**(dataRecord.goAwayPoly)).polyBBox; HUnlock(dataRecord.goAwayPoly); xOffset = -polyRect.left + strucRect.left + 18; yOffset = -polyRect.top + dataRecord.midY + 5; OffsetPoly(dataRecord.goAwayPoly, xOffset, yOffset); OffsetRgn(dataRecord.goAwayRgn, xOffset, yOffset); } if (theWindow->spareFlag) { HLock(dataRecord.zoomPoly); polyRect = (**(dataRecord.zoomPoly)).polyBBox; HUnlock(dataRecord.zoomPoly); xOffset = -polyRect.left + strucRect.right - 34; yOffset = -polyRect.top + dataRecord.midY + 5; OffsetPoly(dataRecord.zoomPoly, xOffset, yOffset); OffsetRgn(dataRecord.zoomRgn, xOffset, yOffset); } if (dataRecord.resizable) { HLock(dataRecord.growPoly); polyRect = (**(dataRecord.growPoly)).polyBBox; HUnlock(dataRecord.growPoly); xOffset = -polyRect.left + dataRecord.midX - 8; yOffset = -polyRect.top + strucRect.bottom - 24; OffsetPoly(dataRecord.growPoly, xOffset, yOffset); OffsetRgn(dataRecord.growRgn, xOffset, yOffset); /* Make the clipRgn which will prevent drawing from occuring within the slider area. This region will later have to be suspended to allow for the drawing of the sliders themselves. When working with clipRgns it is important to remember how the Mac coordinate system works. Recall that the pen hangs down and to the right one pixel of the actual location of the pen. The following few lines compensate for this. */ SetPort(theWindow); OpenRgn(); theRect = theWindow->port.portRect; MoveTo(theRect.left, theRect.top + halfPort); Line (1, 0); Line(halfPort - 1, -halfPort + 1); Line(halfPort - 1, halfPort - 1); Line (1, 0); Line(-halfPort, halfPort); Line(-halfPort, -halfPort); CloseRgn(theWindow->port.clipRgn); SetPort(savedPort); } /* Find how much space is available in each window half for writing the title in. */ dataRecord.halfTitleSpace = halfStruc - FULL_RESERVE; } void ToggleGoAwayBox() { /* Indicates when the close region of a diamond window is selected by drawing an asterisk-like symbol within the region. First the image is drawn into an offscreen BitMap using StuffHex(), then the image is tranferred to the WMgrPort by means of the CopyBits() procedure. */ BitMap closeBitMap; GrafPtr windMngrPort; Rect tempRect, myRect; closeBitMap.baseAddr = NewPtr(0x34); StuffHex(closeBitMap.baseAddr, "002000200020012400A80000"); StuffHex(closeBitMap.baseAddr + 12, "0F8F800000A801240020002000200"); closeBitMap.rowBytes = 2; closeBitMap.bounds.top = closeBitMap.bounds.left = 0; closeBitMap.bounds.bottom = closeBitMap.bounds.right = 13; myRect = closeBitMap.bounds; tempRect = (**dataRecord.goAwayPoly).polyBBox; OffsetRect(&myRect, tempRect.left + 2, tempRect.top + 2); GetWMgrPort(&windMngrPort); CopyBits(&closeBitMap, &windMngrPort->portBits, &closeBitMap.bounds, &myRect, srcXor, NULL); DisposPtr(closeBitMap.baseAddr); } void ToggleZoomBox() { /* As ToggleGoAwayBox(). */ BitMap zoomBitMap; GrafPtr windMngrPort; Rect tempRect, myRect; zoomBitMap.baseAddr = NewPtr(0x34); StuffHex(zoomBitMap.baseAddr, "0020002000A0016400A80010"); StuffHex(zoomBitMap.baseAddr + 12, "0F8F801000A8016400A0002000200"); zoomBitMap.rowBytes = 2; zoomBitMap.bounds.top = zoomBitMap.bounds.left = 0; zoomBitMap.bounds.bottom = zoomBitMap.bounds.right = 13; myRect = zoomBitMap.bounds; tempRect = (**dataRecord.zoomPoly).polyBBox; OffsetRect(&myRect, tempRect.left + 2, tempRect.top + 2); GetWMgrPort(&windMngrPort); CopyBits(&zoomBitMap, &windMngrPort->portBits, &zoomBitMap.bounds, &myRect, srcXor, NULL); DisposPtr(zoomBitMap.baseAddr); } void EraseTitleSpace(Boolean leftSide, short length) { /* Clears space for the window's title to be drawn in. */ RgnHandle theRgn; theRgn = NewRgn(); OpenRgn(); if (leftSide) { Line(length, length); Line(11, -11); Line(-length, -length); Line(-11, 11); } else { Line(length, -length); Line(-11, -11); Line(-length, length); Line(11, 11); } CloseRgn(theRgn); EraseRgn(theRgn); DisposeRgn(theRgn); } void DrawChars(short startSpot, short stopSpot, Ptr theTitle) { /* Draws the characters of the window's title on a diagonal slant. If (start == FIRST_CHAR) then text is drawn on a downward slant, otherwise text is drawn on an upward slant beginning with the character specified by startSpot. */ char ch; short yOffset, index, charWidth, xAdjust; if (startSpot == FIRST_CHAR) yOffset = 8; else yOffset = -8; index = startSpot; while (index <= stopSpot) { ch = *(theTitle + index); charWidth = CharWidth(ch); xAdjust = charWidth >> 1; Move(-xAdjust, 0); DrawChar(ch); Move(-(charWidth - xAdjust) + 8, yOffset); index ++; } } void DrawTitle(WindowPeek theWindow, Rect strucRect) { /* Decides how text should appear, depending on the size of the window and its title. Positions the pen and oversees text drawing. */ Ptr theTitle; short totalWidth, oneSide, adjust, penOffset, mostChars, leftChars; StringHandle titleHandle; titleHandle = theWindow->titleHandle; HLock(titleHandle); theTitle = (Ptr) *titleHandle; totalWidth = (dataRecord.numChars << 3) + 10; oneSide = (strucRect.right - strucRect.left) >> 1; if (totalWidth <= dataRecord.halfTitleSpace) { adjust = ((oneSide - totalWidth) >> 1) + 7; MoveTo(strucRect.left + adjust, dataRecord.midY + adjust); EraseTitleSpace(LEFT_SIDE, totalWidth); Move(16, 7); DrawChars(FIRST_CHAR, dataRecord.numChars, theTitle); } else { mostChars = dataRecord.numChars - dataRecord.leftStop; if (mostChars < dataRecord.leftStop) mostChars = dataRecord.leftStop; if ((mostChars << 3) < (dataRecord.halfTitleSpace)) { /* word break on space */ penOffset = (dataRecord.leftStop << 3) + 5; MoveTo(dataRecord.midX - BOTTOM_RESERVE - 3, strucRect.bottom - BOTTOM_RESERVE - 3); Move(-penOffset, -penOffset); EraseTitleSpace(LEFT_SIDE, penOffset); Move(14, 5); DrawChars(FIRST_CHAR, dataRecord.leftStop, theTitle); /* don't forget to remove the excess space */ penOffset = (dataRecord.numChars - dataRecord.leftStop - 1) << 3; MoveTo(dataRecord.midX + BOTTOM_RESERVE + 3, strucRect.bottom - BOTTOM_RESERVE - 3); EraseTitleSpace(!LEFT_SIDE, penOffset + 5); Move(1, -8); DrawChars(dataRecord.leftStop + 2, dataRecord.numChars, theTitle); } else { /* no word break on space */ leftChars = dataRecord.halfTitleSpace >> 3; penOffset = dataRecord.halfTitleSpace + 4; MoveTo(dataRecord.midX - BOTTOM_RESERVE - 3, strucRect.bottom - BOTTOM_RESERVE - 3); Move(-penOffset, -penOffset); EraseTitleSpace(LEFT_SIDE, penOffset); Move(14, 5); DrawChars(FIRST_CHAR, leftChars, theTitle); MoveTo(dataRecord.midX + BOTTOM_RESERVE + 3, strucRect.bottom - BOTTOM_RESERVE - 3); mostChars = leftChars << 1; if (mostChars > dataRecord.numChars) { mostChars = dataRecord.numChars; penOffset = ((dataRecord.numChars - leftChars) << 3) + 4; } EraseTitleSpace(!LEFT_SIDE, penOffset); Move(0, -7); DrawChars(leftChars + 1, mostChars, theTitle); } } HUnlock(titleHandle); } void DrawWindow(WindowPeek theWindow, long param) { /* Draws diamond window frames and titles as appropriate. */ Rect strucRect; short halfPort, halfStruc, index; if (theWindow->visible) switch(LoWord(param)) { case wInGoAway: ToggleGoAwayBox(); break; case wInZoomIn: case wInZoomOut: ToggleZoomBox(); break; default: /* Draw window frame. */ if (theWindow->titleWidth) { CalcRgns(theWindow); theWindow->titleWidth = FALSE; } if (dataRecord.zoomedOut) strucRect = dataRecord.stdRect; else strucRect = dataRecord.myRect; InsetRect(&strucRect, -26, -26); halfStruc = halfPort = (strucRect.right - strucRect.left) >> 1; halfPort -= 26; MoveTo(strucRect.left, dataRecord.midY); Line(halfStruc, -halfStruc); PenSize(3, 1); Line(halfStruc, halfStruc); Line(-halfStruc, halfStruc); PenSize(1, 1); Line(-halfStruc, -halfStruc); /* Draw content stuff */ EraseRgn(dataRecord.titleRgn); /* Outline the content region {and the title region}. */ Line(26, 0); Line(halfPort, halfPort); Line(halfPort, -halfPort); Line(25, 0); if (theWindow->hilited) { MoveTo(strucRect.left + 23, dataRecord.midY + 2); index = halfStruc - 3; for (halfStruc = index - 20; halfStruc < index; halfStruc += 4) { Line(halfStruc, halfStruc); Line(halfStruc, -halfStruc); Move(-(halfStruc << 1) - 4, 0); } if (theWindow->goAwayFlag) { PenPat(&white); PenSize(1, 1); MoveTo(strucRect.left + 17, dataRecord.midY + 12); Line(8, -8); Move(0, 20); Line(10, -10); PenPat(&black); EraseRgn(dataRecord.goAwayRgn); FramePoly(dataRecord.goAwayPoly); } if (theWindow->spareFlag) { PenPat(&white); PenSize(1, 1); MoveTo(strucRect.right - 17, dataRecord.midY + 12); Line(-8, -8); Move(0, 20); Line(-10, -10); PenPat(&black); EraseRgn(dataRecord.zoomRgn); FramePoly(dataRecord.zoomPoly); } if (dataRecord.resizable) { InsetRgn(dataRecord.growRgn, -2, 0); EraseRgn(dataRecord.growRgn); InsetRgn(dataRecord.growRgn, 2, 0); FramePoly(dataRecord.growPoly); } } /* if window is hilited */ DrawTitle(theWindow, strucRect); break; } /* end switch */ } NewTitle(WindowPeek theWindow, Ptr theTitle) { /* Resets the handle size for the window's title, then BlockMove()s the new information into it. Next the space closest to the true center of the title is found and recorded in the variable leftStop {if no space is found the entire title's length is stored in leftStop}. This information, coupled with the window's current size, is used to determine how the the window's title should be drawn {all on the left side, split at a space and part drawn on each side, etc.}. NewTitle() should only be called when the window is given a new title. */ char ch; GrafPtr savedPort; Ptr middleChar; RgnHandle theRgn; short leftChars, index; StringHandle titleHandle; WindowPeek windMgrPort; dataRecord.numChars = *theTitle; titleHandle = theWindow->titleHandle; SetHandleSize(titleHandle, dataRecord.numChars + 1); BlockMove(theTitle, *titleHandle, dataRecord.numChars + 1); HLock(titleHandle); leftChars = dataRecord.numChars >> 1; /* divide in half */ middleChar = theTitle + leftChars; for (index = 0; index <= leftChars; index ++) { ch = *(middleChar - index); if (ch == 0x20) { dataRecord.leftStop = leftChars - index - 1; break; } else { ch = *(middleChar + index); if (ch == 0x20) { dataRecord.leftStop = leftChars + index - 1; break; } } } if (index > leftChars) dataRecord.leftStop = dataRecord.numChars; HUnlock(titleHandle); /* When dataRecord.titleRgn == NULL, the window is new and therefore its titleRgn has not yet been properly set up by CalcRgns(). Setting a clipRgn to an uninitialized region is a fatal error so SetClip() should NOT be called under this circumstance. */ if ((theWindow->visible) && (dataRecord.titleRgn != NULL)) { GetPort(&savedPort); GetWMgrPort(&windMgrPort); SetPort(windMgrPort); theRgn = NewRgn(); GetClip(theRgn); /* The visRgn does not include any of the window's strucRgn, only the visible portion of its contRgn. There's no point in dealing with the entire visible strucRgn, just the part of it used to display the window's title since that's all that's being altered. So the WDEF just sets the window manager's clipRgn to the window's titleRgn and calls ClipAbove() to subtract the strucRgns of all visible window's in front of the window whos title has been changed. */ SetClip(dataRecord.titleRgn); ClipAbove(theWindow); DrawWindow(theWindow, DRAW_WINDOW_FRAME); SetClip(theRgn); /* SetClip() copies the specified region into the clipRgn member of the current port. It's up to the programmer to release the memory occupied by the original region. */ DisposeRgn(theRgn); SetPort(savedPort); } } void DrawGrowIcon(WindowPeek theWindow) { /* Draws the part of the grow icon that is in the content region of the window. It is not feasible to draw the gIcon as part of the window frame because, although the icon is properly drawn with much less effort, it is often times incorrectly erased by the Window Manager when the window is resized {the WManager has to erase the content region to ensure that no desktop slop shows through}. */ GrafPtr savedPort; PenState savedPenState; Rect portRect; RgnHandle clipRgn; short halfPort; if (dataRecord.resizable) if (theWindow->visible) { GetPort(&savedPort); SetPort(theWindow); GetPenState(&savedPenState); PenNormal(); clipRgn = NewRgn(); GetClip(clipRgn); /* Must take into consideration the coordinates of the origin in case SetOrigin() has been called with values other than (0, 0). Remember, this drawing occurs within the window's own grafport. */ portRect = theWindow->port.portRect; halfPort = (portRect.right - portRect.left) >> 1; MoveTo(portRect.left, portRect.top + halfPort); portRect.top -= 26; ClipRect(&portRect); Line(halfPort, -halfPort); Line(0, -25); Move(0, 25); Line(halfPort, halfPort); SetPenState(&savedPenState); SetClip(clipRgn); DisposeRgn(clipRgn); SetPort(savedPort); } } void GrowWindowGrow(WindowPeek theWindow, Rect* rectPtr) { /* Draws the grow image for the window. Diamond windows grow and shrink at twice the normal rate and only movement in the y-direction effects them when they are being resized. To find the new length of each side, (*rectPtr).bottom is subtracted from dataRecord.midY, the y-coordinate of the middle of the window. */ short length, longLength; length = longLength = rectPtr->bottom - dataRecord.midY - 1; longLength += 26; MoveTo(dataRecord.midX - length, dataRecord.midY); PenPat(&white); Line(length, -length); Line(length, length); Line(-length, length); Line(-length, -length); PenPat(&gray); Line(-26, 0); Move(longLength, -length); Line(0, -26); Move(length, longLength); Line(26, 0); PenPat(&white); Line(-longLength, longLength); Line(-longLength, -longLength); Line(longLength, -longLength); Line(longLength, longLength); /* The Window Manager automatically resets the pen pattern to black when it stops calling this function. */ } void SetUpStdZoom(void) { /* Sets up the stdState Rect so the window will be zoom ready. This rectangle is always centered onscreen and does not take into account any maximum window size you may entend to enforce using GrowWindow(). */ GrafPtr windMPort; Rect theRect; short xDistance, yDistance; GetPort(&windMPort); theRect = windMPort->portRect; InsetRect(&theRect, SCREEN_MARGIN, SCREEN_MARGIN + FRAME_WIDTH); theRect.top += MBarHeight; theRect.right -= SHADOW; theRect.bottom -= 2; /* Make sure x and yDistance are even. */ xDistance = (theRect.right - theRect.left) & MAKE_EVEN; yDistance = (theRect.bottom - theRect.top) & MAKE_EVEN; if (xDistance > yDistance) { OffsetRect(&theRect, (xDistance - yDistance) >> 1, 0); theRect.right = theRect.left + yDistance; } else if (yDistance > xDistance) { OffsetRect(&theRect, 0, (yDistance - xDistance) >> 1); theRect.bottom = theRect.top + xDistance; } dataRecord.stdRect = theRect; } void InitNewWindow(WindowPeek theWindow) { /* Sets up various window regions and allocates memory necessary for the operation of diamond shaped windows. */ Rect theRect; Str255 theTitle; theWindow->strucRgn = NewRgn(); theWindow->contRgn = NewRgn(); if (theWindow->goAwayFlag) { dataRecord.goAwayPoly = OpenPoly(); MoveTo(0, 0); Line(8, -8); Line(8, 8); Line(-8, 8); Line(-8, -8); ClosePoly(); dataRecord.goAwayRgn = NewRgn(); OpenRgn(); FramePoly(dataRecord.goAwayPoly); CloseRgn(dataRecord.goAwayRgn); } if (dataRecord.resizable) { dataRecord.growPoly = OpenPoly(); MoveTo(0, 0); Line(8, -8); Line(8, 8); Line(-8, 8); Line(-8, -8); Line(5, -5); Line(-2, -2); Line(5, -5); Line(5, 5); Line(-1, 1); ClosePoly(); dataRecord.growRgn = NewRgn(); OpenRgn(); MoveTo(0, 0); Line(5, -5); Line(-2, -2); Line(5, -5); Line(5, 5); Line(-2, 2); Line(5, 5); Line(-8, 8); Line(-8, -8); CloseRgn(dataRecord.growRgn); } if (theWindow->spareFlag) { dataRecord.zoomPoly = OpenPoly(); MoveTo(5, -5); Line(3, -3); Line(8, 8); Line(-8, 8); Line(-8, -8); Line(5, -5); Line(5, 5); Line(-5, 5); ClosePoly(); dataRecord.zoomRgn = NewRgn(); OpenRgn(); FramePoly(dataRecord.goAwayPoly); CloseRgn(dataRecord.zoomRgn); SetUpStdZoom(); dataRecord.zoomedOut = FALSE; } /* Initialize the global variable dataRecordHdl so data can be transferred from the global variable dataRecord into the window's private storage area. */ dataRecordHdl = (DataRecordHdl) NewHandle(sizeof(DataRecord)); theWindow->dataHandle = (Handle) dataRecordHdl; theRect = theWindow->port.portRect; if (theRect.bottom > theRect.right) { /* To ensure that each side of a window's portRect is even, the value is ANDed with MAKE_EVEN, that is 0xFFFE. */ theRect.right &= MAKE_EVEN; theRect.bottom = theRect.right; } else { theRect.bottom &= MAKE_EVEN; theRect.right = theRect.bottom; } theWindow->port.portRect = theRect; /* Save title information that will allow diamond window title to be drawn more quiclky. */ BlockMove(*(theWindow->titleHandle), theTitle, 0xFF); dataRecord.titleRgn = NULL; NewTitle(theWindow, (Ptr) theTitle); dataRecord.titleRgn = NewRgn(); } long DoHit(WindowPeek theWindow, Point mouseClick) { /* Determines if a diamond window was hit by a mouseClick. If so, returns the region in which the click occured. */ if (theWindow->visible) if (theWindow->hilited) { if (theWindow->goAwayFlag) if (PtInRgn(mouseClick, dataRecord.goAwayRgn)) return(wInGoAway); if (dataRecord.resizable) if (PtInRgn(mouseClick, dataRecord.growRgn)) return(wInGrow); if (theWindow->spareFlag) if (PtInRgn(mouseClick, dataRecord.zoomRgn)) return(dataRecord.zoomedOut ? wInZoomIn : wInZoomOut); if (PtInRgn(mouseClick, dataRecord.titleRgn)) return(wInDrag); if (PtInRgn(mouseClick, theWindow->contRgn)) return(wInContent); } else { if (PtInRgn(mouseClick, dataRecord.titleRgn)) return(wInDrag); if (PtInRgn(mouseClick, theWindow->strucRgn)) return(wInContent); } } void WindowDisposal(WindowPeek theWindow) { /* Releases memory occupied by auxiliary window data. */ DisposeRgn(dataRecord.titleRgn); if (theWindow->goAwayFlag) { KillPoly(dataRecord.goAwayPoly); DisposeRgn(dataRecord.goAwayRgn); } if (dataRecord.resizable) { KillPoly(dataRecord.growPoly); DisposeRgn(dataRecord.growRgn); } if (theWindow->spareFlag) { KillPoly(dataRecord.zoomPoly); DisposeRgn(dataRecord.zoomRgn); } DisposHandle(theWindow->dataHandle); } pascal long main(varCode, theWindow, message, param) short varCode; WindowPeek theWindow; short message; long param; { /* Sets up registers, copies dataHandle information into global variables, dispatches control to other routines, and copies updated information back into the window's dataHandle. */ long returnVal = 0L; RememberA0(); SetUpA4(); if (message != wNew) { dataRecordHdl = (DataRecordHdl) theWindow->dataHandle; BlockMove(*dataRecordHdl, &dataRecord, sizeof(DataRecord)); } switch (message) { case wDraw: DrawWindow(theWindow, param); break; case wHit: returnVal = DoHit(theWindow, topLeft(param)); break; case wJUST_DRAGGED: theWindow->titleWidth = FALSE; case wCalcRgns: CalcRgns(theWindow); break; case wNew: theWindow->spareFlag = varCode & ZOOM_MASK; dataRecord.resizable = !(varCode & NO_GROW_MASK); InitNewWindow(theWindow); break; case wDispose: WindowDisposal(theWindow); RestoreA4(); return(returnVal); break; case wDrawGIcon: DrawGrowIcon(theWindow); break; case wGrow: GrowWindowGrow(theWindow, (Rect *) param); break; case wNEW_TITLE: NewTitle(theWindow, (Ptr) param); break; } HLock(dataRecordHdl); BlockMove(&dataRecord, *dataRecordHdl, sizeof(DataRecord)); HUnlock(dataRecordHdl); RestoreA4(); return(returnVal); }